// Author: Ivan Chau
package uk.ac.cam.kcic2.math;

public class Matrix4 {

	private final double[][] m = new double[Params.MATRIX_DIM][Params.MATRIX_DIM];

	public Matrix4(double[][] values){
		assert values.length == Params.MATRIX_DIM;
		for (int i = 0; i < Params.MATRIX_DIM; i++){
			assert values[i].length == Params.MATRIX_DIM;
		}

		for (int row = 0; row < Params.MATRIX_DIM; row++){
			for (int column = 0; column < Params.MATRIX_DIM; column++){
				assert values[row][column] != Double.NaN || 
						values[row][column] != Double.NEGATIVE_INFINITY ||
								values[row][column] != Double.POSITIVE_INFINITY;
				m[row][column] = values[row][column];
			}
		}

	}

	public double get(int row, int column){
		assert row >= Params.X && row <= Params.W;
		assert column >= Params.X && column <= Params.W;
		
		return m[row][column];
	}

	public Matrix4 mult(Matrix4 arg){
		double[][] result = new double[Params.MATRIX_DIM][Params.MATRIX_DIM];
		double[][] mat2 = arg.m;
		
		for (int row = 0; row < Params.MATRIX_DIM; row++){
			for (int column = 0; column < Params.MATRIX_DIM; column++){
				for (int index = 0; index < Params.MATRIX_DIM; index++){
					result[row][column] += m[row][index] * mat2[index][column];
				}
			}
		}
		return new Matrix4(result);
	}

	public Vector3D mult(Vector3D vector){
		Vector3DHomo vec = new Vector3DHomo(vector);
		double[] result = new double[Params.MATRIX_DIM];
		for (int row = 0; row < Params.MATRIX_DIM; row++){
			for (int column = 0; column < Params.MATRIX_DIM; column++){
				result[row] += m[row][column]*vec.get(column);
			}
		}
		return new Vector3D(new Vector3DHomo(result));
	}
}
